#include "Tkgles.h"
#include "graphic.h"
#include <math.h>
#include <float.h>
#include "Triangle.h"

EXPORT void DrawPoint(GLint index) {

	Context * context = getContext();
	Vect3D * coord;
	INT width,height,devx,devy;

	if (context){
		coord = &(context->VertexArray.WindowCoord[index]);
		width = context->ViewPort.px;
		height = context->ViewPort.py;
		devx = (GLint)coord[0].x;
		devy = (GLint)(-coord[0].y);
		if ( devx < width && devx > 0 && devy < height && devy > 0){
			draw(devx,devy,BLACK,&(glDisplay->devbmp));
		}
	}

}
LOCAL void RasterLine(){
    
}

EXPORT void DrawLine(GLint from, GLint to) {

	Context * context = getContext();
	Vect3D * coordFrom, * coordTo;
	INT width,height,devxFrom,devxTo,devyFrom,devyTo;

	if (context){
		coordFrom = &(context->VertexArray.WindowCoord[from]);
		coordTo = &(context->VertexArray.WindowCoord[to]);
		width = context->ViewPort.px;
		height = context->ViewPort.py;
		devxFrom = (GLint)coordFrom[0].x;
		devyFrom = (GLint)(-coordFrom[0].y);
		devxTo = (GLint)coordTo[0].x;
		devyTo = (GLint)(-coordTo[0].y);
		draw_line(devxFrom,devyFrom,devxTo,devyTo,BLACK,&(glDisplay->devbmp));
	}

}

//Render triangle using point sampling
EXPORT void DrawTriangle(GLint first){
	//printf("Drawing a triangle\n");
	Context * context = getContext();
	GLint i,top,bot,temp,coord[3][3];
	GLfloat	lowest_y,highest_y,coefA,coefB,coefC,x1,x2,temp_float,depth[3];
    Color * vertex_color[3],* pTemp;

        //Find the highest vertex and lowest vertex of triangle
        //Highest vertext index is store in top, it's y-coord is highest_y
        //and lowest_y store y-coord of lowest vertext
	lowest_y = context->ViewPort.oy + (context->ViewPort.py/2);
	highest_y = context->ViewPort.oy - (context->ViewPort.py/2);
	top = 0;
	for (i = first; i <  first + 3; i++){
		if(context->VertexArray.WindowCoord[i].y > highest_y){
			top = i-first;
			highest_y = context->VertexArray.WindowCoord[i].y;
		}
		if(context->VertexArray.WindowCoord[i].y < lowest_y){
			lowest_y = context->VertexArray.WindowCoord[i].y;
		}
		coord[i-first][0] = (GLint)context->VertexArray.WindowCoord[i].x;
		coord[i-first][1] = (GLint)context->VertexArray.WindowCoord[i].y;
		coord[i-first][2] = i;
        depth[i-first] = context->VertexArray.WindowCoord[i].z;
        vertex_color[i-first]=get_color(i);
	}

	//Swap top coordinate to first order place in coord array
    //After this the vertex store in coord[0] has hightest y-coord
	if(top != 0){
		temp = coord[top][0];
		coord[top][0] = coord[0][0];
		coord[0][0] = temp;
		temp = coord[top][1];
		coord[top][1] = coord[0][1];
		coord[0][1] = temp;
		temp = coord[top][2];
		coord[top][2] = coord[0][2];
		coord[0][2] = temp;

		temp_float = depth[top];
		depth[top] = depth[0];
		depth[0]= temp_float;

        pTemp = vertex_color[top];
        vertex_color[top] = vertex_color[0];
        vertex_color[0] = pTemp;
	}
    if (coord[1][1] < coord[2][1]){
		temp = coord[2][0];
		coord[2][0] = coord[1][0];
		coord[1][0] = temp;
		temp = coord[2][1];
		coord[2][1] = coord[1][1];
		coord[1][1] = temp;
		temp = coord[2][2];
		coord[2][2] = coord[1][2];
		coord[1][2] = temp;

		temp_float = depth[top];
		depth[2] = depth[1];
		depth[1]= temp_float;

        pTemp = vertex_color[2];
        vertex_color[2] = vertex_color[1];
        vertex_color[1] = pTemp;
    }
    top = coord[0][1] > (context->ViewPort.oy+context->ViewPort.py)? (context->ViewPort.oy+context->ViewPort.py):coord[0][1];
    bot = coord[2][1] < (context->ViewPort.oy-context->ViewPort.py + 1)? (context->ViewPort.oy-context->ViewPort.py + 1):coord[2][1];

//    depth[0] = depth[0] < 0 ? 0 : depth[0];
//    depth[1] = depth[1] < 0 ? 0 : depth[1];
//    depth[2] = depth[2] < 0 ? 0 : depth[2];
//	printf("Depth value :%f %f %f\n",depth[0],depth[1],depth[2]);
//	printf("Triangle's vertices :%d, %d, %d\n",coord[0][0],coord[0][1],coord[0][2]);
//	printf("Triangle's vertices :%d, %d, %d\n",coord[1][0],coord[1][1],coord[1][2]);
//	printf("Triangle's vertices :%d, %d, %d\n",coord[2][0],coord[2][1],coord[2][2]);

    coefA = ((GLfloat)(coord[1][0] - coord[0][0]))/(coord[1][1] - coord[0][1]);
    //coefA = coefA > FLT_MAX?FLT_MAX:coefA;
    //coefA = coefA < FLT_MIN?FLT_MIN:coefA;
    coefB = ((GLfloat)(coord[2][0] - coord[0][0]))/(coord[2][1] - coord[0][1]);
    //coefB = coefB > FLT_MAX?FLT_MAX:coefB;
    //coefB = coefB < FLT_MIN?FLT_MIN:coefB;
    coefC = ((GLfloat)(coord[2][0] - coord[1][0]))/(coord[2][1] - coord[1][1]);
    //coefC = coefC > FLT_MAX?FLT_MAX:coefC;
    //coefC = coefC < FLT_MIN?FLT_MIN:coefC;
    //printf("Edge coefficient: %f, %f, %f\n", coefA,coefB,coefC);

    for (i = top;i >= bot;i--){
        if(coord[0][1] == coord[1][1]){
            //y0 = y1
            if(coord[0][0] == coord[1][0]){
                //Vertical line
                RasterLine(coord[0],coord[2],vertex_color[0],vertex_color[2]);
                //stop rastering triangle
            }else if(coord[0][0] == coord[2][0]){
                //x0 = x2 => right triangle
               // printf("pharse 1\n");
                x1 = coord[0][0];
                x2 = coefC*(i-coord[1][1]) + coord[1][0];
            } else if(coord[1][0] == coord[2][0]){
                //x1 = x2 =>ri4ght triangle
                //printf("pharse 2\n");
                x1 = coefB*(i-coord[0][1]) + coord[0][0];
                x2 = coord[0][0];
            } else{
                //Not a right triangle
                x1 = coefB*(i-coord[0][1]) + coord[0][0];
                x2 = coefC*(i-coord[1][1]) + coord[1][0];
            }
        } else if (coord[0][1] == coord[2][1]){
            //y0 = y2
            if(coord[0][0] == coord[2][0]){
                RasterLine(coord[0],coord[1],vertex_color[0],vertex_color[1]);
            }else if(coord[0][0] == coord[1][0]){
                //right triangle
                x1 = coord[0][0];
                x2 = coefC*(i-coord[1][1]) + coord[1][0];
            }else if(coord[2][0] == coord[1][0]){
                //right triangle
                x1 = coord[1][0];
                x2 = coefB*(i-coord[0][1]) + coord[0][0];
            }else {
                //Not a right triangle
                x1 = coefB*(i-coord[0][1]) + coord[0][0];
                x2 = coefC*(i-coord[1][1]) + coord[1][0];
            }
        } else if(coord[1][1] == coord[2][1]){
            if(coord[1][0] == coord[2][0]){
                RasterLine(coord[0],coord[2],vertex_color[0],vertex_color[2]);
            }else if(coord[0][0] == coord[1][0]){
                //right triangle
                x1 = coord[0][0];
                x2 = coefB*(i-coord[0][1]) + coord[0][0];
            }else if(coord[0][0] == coord[2][0]){
                //right triangle
                x1 = coord[0][0];
                x2 = coefA*(i-coord[0][1]) + coord[0][0];
            }else {
                //not a right triangle
                x1 = coefA*(i-coord[0][1]) + coord[0][0];
                x2 = coefB*(i-coord[0][1]) + coord[0][0];
            }
        } else {
            if(coord[0][0] == coord[1][0] == coord[2][0]){
                RasterLine(coord[0],coord[1],vertex_color[0],vertex_color[1]);
                RasterLine(coord[0],coord[2],vertex_color[0],vertex_color[2]);
            }else if(coord[0][0] == coord[1][0]){
                if(i >= coord[1][1]){
                    x1 = coord[0][0];
                    x2 = coefB*(i-coord[0][1]) + coord[0][0];
                }else{
                    x1 = coefC*(i-coord[1][1]) + coord[1][0];
                    x2 = coefB*(i-coord[0][1]) + coord[0][0];
                }

            } else if(coord[0][0] == coord[2][0]){
                if(i >= coord[1][1]){
                    x1 = coord[0][0];
                    x2 = coefA*(i-coord[0][1]) + coord[0][0];
                }else{
                    x1 = coord[0][0];
                    x2 = coefC*(i-coord[1][1]) + coord[1][0];
                }
            } else if(coord[1][0] == coord[2][0]){
                if(i >= coord[1][1]){
                    x1 = coefA*(i-coord[0][1]) + coord[0][0];
                    x2 = coefB*(i-coord[0][1]) + coord[0][0];
                }else{
                    x1 = coord[1][0];
                    x2 = coefB*(i-coord[0][1]) + coord[0][0];
                }
            }else {
                if(i >= coord[1][1]){
                    x1 = coefA*(i-coord[0][1]) + coord[0][0];
                    x2 = coefB*(i-coord[0][1]) + coord[0][0];
                }else{
                    x1 = coefC*(i-coord[1][1]) + coord[1][0];
                    x2 = coefB*(i-coord[0][1]) + coord[0][0];
                }
            }
        }
        MakeSpan(x1,x2,i,coord,vertex_color,depth);
    }
    Kfree(vertex_color[0]);
	Kfree(vertex_color[1]);
	Kfree(vertex_color[2]);
}


